#pragma once
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#include "logger.hpp"
#include "singleton.hpp"

namespace yx
{
    const static int BACKLOG = 10;
    class TcpServer
    {
        friend class yx::pattern::Singleton<TcpServer>;

    private:
        int16_t _port;      // 端口
        int _listen_sockfd; // 监听套接字

    private:
        TcpServer(int16_t port)
            : _port(port), _listen_sockfd(-1)
        {
            initServer();
        }

        ~TcpServer()
        {
            if (_listen_sockfd >= 0)
            { // 关闭监听套接字
                close(_listen_sockfd);
            }
        }

        // 将拷贝构造函数和拷贝赋值函数私有或删除（防拷贝）
        TcpServer(const TcpServer &) = delete;
        TcpServer *operator=(const TcpServer &) = delete;

    public:
        // 初始化服务器
        void initServer()
        {
            createSocket();
            bindAddress();
            setListen();
            info("init tcp server success!!!\n");
        }

        // 创建套接字
        void createSocket()
        {
            _listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_listen_sockfd < 0)
            {
                fatal("create socket fail!!!\n");
                exit(1);
            }

            // 设置端口复用
            int opt = 1;
            setsockopt(_listen_sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
            info("create socket success!!!\n");
        }

        // 绑定
        void bindAddress()
        {
            struct sockaddr_in local;
            memset(&local, 0, sizeof(local));
            local.sin_family = AF_INET;
            local.sin_port = htons(_port);
            local.sin_addr.s_addr = INADDR_ANY;

            if (bind(_listen_sockfd, (struct sockaddr *)&local, sizeof(local)))
            {
                fatal("bind address error!!!\n");
                exit(2);
            }
            info("bind address success!!!\n");
        }

        // 设置监听
        void setListen()
        {
            if (listen(_listen_sockfd, BACKLOG) < 0)
            {
                fatal("set listen error!!!\n");
                exit(3);
            }
            info("set listen success!!!\n");
        }
        // // 获取链接sockfd
        // int getAcceptSocket()
        // {

        // }
        // 获取监听套接字
        int getListenSockfd()
        {
            return _listen_sockfd;
        }
    };
}